package com.example.demo.core.util;

import com.example.demo.core.constant.TimeFormatConstant;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.TimeZone;

/**
 * @author yj
 * @date 2021-05-12 9:19
 */
public class JacksonUtil {

    private static final ObjectMapper OBJECT_MAPPER;

    private static final JavaTimeModule JAVA_TIME_MODULE;

    static {
        OBJECT_MAPPER = new ObjectMapper();
        JAVA_TIME_MODULE = new JavaTimeModule();
        // 序列化配置,针对java8时间
        JAVA_TIME_MODULE.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(TimeFormatConstant.StripingConstant.YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)));
        JAVA_TIME_MODULE.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(TimeFormatConstant.StripingConstant.YEAR_MONTH_DAY)));
        JAVA_TIME_MODULE.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(TimeFormatConstant.HOUR_MINUTE_SECOND)));
        // 反序列化配置,针对java8时间
        JAVA_TIME_MODULE.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(TimeFormatConstant.StripingConstant.YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)));
        JAVA_TIME_MODULE.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(TimeFormatConstant.StripingConstant.YEAR_MONTH_DAY)));
        JAVA_TIME_MODULE.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(TimeFormatConstant.HOUR_MINUTE_SECOND)));
        //默认分区8
        OBJECT_MAPPER.setTimeZone(TimeZone.getTimeZone(TimeFormatConstant.TIME_ZONE_FORMAT));
    }

    public static <T> String objectToJson(T data) {
        try {
            if (RegexUtil.checkObjectIsNull(data)) {
                return null;
            }
            return OBJECT_MAPPER.writeValueAsString(data);
        } catch (JsonProcessingException e) {
            return null;
        }
    }


    public static <T> String objectToJsonAsTimeFormat(T data) {
        try {
            if (RegexUtil.checkObjectIsNull(data)) {
                return null;
            }
            //注册时间模块
            OBJECT_MAPPER.registerModule(JAVA_TIME_MODULE);
            //开启将时间写成时间戳格式
            OBJECT_MAPPER.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
            return OBJECT_MAPPER.writeValueAsString(data);
        } catch (JsonProcessingException e) {
            return null;
        }
    }

    /**
     * 属性为Null不序列化
     */
    public static <T> String objectToJsonWithoutNull(T data) {
        try {
            if (RegexUtil.checkObjectIsNull(data)) {
                return null;
            }
            OBJECT_MAPPER.registerModule(JAVA_TIME_MODULE);
            OBJECT_MAPPER.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
            //属性为NULL不序列化
            OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            return OBJECT_MAPPER.writeValueAsString(data);
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * 将json结果集转化为对象
     *
     * @param data  json数据
     * @param clazz 对象中的object类型
     */
    public static <T> T jsonToClassEntity(String data, Class<T> clazz) {
        try {
            if (RegexUtil.checkObjectIsNull(data)) {
                return null;
            }
            return OBJECT_MAPPER.readValue(data, clazz);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * json字符串转JsonNode对象
     *
     * @param data json对象
     */
    public static JsonNode jsonToJsonNode(String data) {
        try {
            if (RegexUtil.checkObjectIsNull(data)) {
                return null;
            }
            return OBJECT_MAPPER.readTree(data);
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * Jackson的JsonNode类转化为实体类
     *
     * @param jsonNode jsonNode节点
     * @param clazz    类型
     * @param <T>      泛型
     */
    public static <T> T jsonNodeToClassEntity(JsonNode jsonNode, Class<T> clazz) {
        try {
            if (RegexUtil.checkObjectIsNull(jsonNode)) {
                return null;
            }
            return OBJECT_MAPPER.readValue(jsonNode.traverse(), clazz);
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * Jackson的JsonNode类转化为实体类集合
     *
     * @param <T>      泛型
     * @param jsonNode jsonNode对象
     * @param clazz    类型
     */
    public static <T> List<T> jsonNodeToList(JsonNode jsonNode, Class<T> clazz) {
        try {
            if (RegexUtil.checkObjectIsNull(jsonNode)) {
                return null;
            }
            //忽略多余的字段
            OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            //忽略空字段
            OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            return OBJECT_MAPPER.readValue(
                    jsonNode.traverse(),
                    OBJECT_MAPPER.getTypeFactory().constructParametricType(
                            List.class,
                            clazz
                    )
            );
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 将json数据转换成pojo对象list
     */
    public static <T> List<T> jsonToList(String data, Class<T> clazz, boolean disableNotNull) {
        try {
            if (RegexUtil.checkObjectIsNull(data)) {
                return null;
            }
            //如果是null或者true
            if (disableNotNull) {
                OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            }
            return OBJECT_MAPPER.readValue(data,
                    OBJECT_MAPPER.getTypeFactory().constructParametricType(
                            List.class,
                            clazz
                    )
            );
        } catch (Exception e) {
            return null;
        }
    }

}